package cn.rxmind.dlog.common;

import org.springframework.context.ApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * @description 
 *
 * @author renxin
 * @email renxinzhiliangzhi@163.com
 * @date 2020/7/11 1:17 下午
 */
public abstract class AbstractDLogInterceptor extends HandlerInterceptorAdapter {

    /**  DLog核心配置 */
    private DLogProperties dLogProperties;

    /**  接口访问日志数据缓冲区 */
    private DLogDataBuffer dLogDataBuffer;

    /**  spring容器上下文 */
    private ApplicationContext applicationContext;

    public AbstractDLogInterceptor(DLogProperties dLogProperties, DLogDataBuffer dLogDataBuffer, ApplicationContext applicationContext) {

        this.dLogProperties = dLogProperties;
        this.dLogDataBuffer = dLogDataBuffer;
        this.applicationContext = applicationContext;
    }

    @Override
    public final void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        if(!(handler instanceof HandlerMethod)){
            return;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        if(DLogLocalData.getDLogData() == null || !needCollect(request,handlerMethod,dLogProperties)){
            return;
        }
        DLogData dLogData = DLogLocalData.getDLogData();
        dLogData.setParam(createExtendParam(request,response,handler));
        dLogDataBuffer.add(dLogData);
        if(dLogDataBuffer.size() >= dLogProperties.getSendBatchCount()){
            applicationContext.publishEvent(new DLogDataCanSendEvent(this,dLogProperties.getSendBatchCount()));
        }
        DLogLocalData.remove();
    }

    /**
     * 这个方法用于封装扩展参数，这里默认实现啥都不做，如有需要交给子类去实现
     *
     * @param request
     * @param response
     * @param handler
     * @return
     */
    protected abstract Map<String,Object> createExtendParam(HttpServletRequest request, HttpServletResponse response, Object handler);

    /**
     * 判定该接口请求是否应该被收集
     *
     * @param request
     * @param handlerMethod
     * @param dLogProperties
     * @return
     */
    protected abstract boolean needCollect(HttpServletRequest request,HandlerMethod handlerMethod,DLogProperties dLogProperties);

}
